home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / v8n08.arc / MOUSECTL.ASM < prev    next >
Assembly Source File  |  1989-03-28  |  30KB  |  606 lines

  1. ;------------------------------------------------------------------------;
  2. ;  MOUSE.CTL - Enhances mouse sensitivity control.                       ;
  3. ;  PC Magazine - Michael J. Mefford                                      ;
  4. ;------------------------------------------------------------------------;
  5. _TEXT          SEGMENT PUBLIC 'CODE'
  6.                ASSUME  CS:_TEXT,DS:_TEXT,ES:_TEXT,SS:_TEXT
  7.                ORG     100H
  8. START:         JMP     INITIALIZE
  9.  
  10. ;              DATA AREA
  11. ;              ---------
  12. SIGNATURE      DB      CR,SPACE,SPACE,SPACE,CR,LF
  13. COPYRIGHT      DB      "MOUSECTL 1.0 (C) 1988 Ziff Communications Co.",CR,LF
  14. PROGRAMMER     DB      "PC Magazine ",BOX," Michael J. Mefford",CR,LF,LF,"$"
  15.                DB      CTRL_Z
  16.  
  17. CR             EQU     13
  18. LF             EQU     10
  19. CTRL_Z         EQU     26
  20. SPACE          EQU     32
  21. BELL           EQU     7
  22. BOX            EQU     254
  23. IRET_CODE      EQU     0CFH
  24.  
  25. OLD_INT_33     DW      ?,?
  26. OLD_INT_10     DW      ?,?
  27.  
  28. VIDEO_MODE     DB      ?
  29. DISPLAY_MODE   EQU     49H                     ;BIOS data.
  30. TEXT_MODE      EQU     0                       ;Text video mode flag.
  31. GRAPHICS       EQU     1                       ;Graphics video mode flag.
  32. CHAR_WIDTH     DW      ?                       ;Adjustment for text cell size.
  33. GRAPHICS_WIDTH DW      ?                       ;Adjustment for graphics cell.
  34.  
  35. MOUSE_VARIABLES LABEL BYTE
  36. HORZ_LAST         DW   0                       ;Mouse driver mickey count total.
  37. VERT_LAST         DW   0
  38. HORZ_ADJUSTED     DW   0                       ;Mickey total application sees.
  39. VERT_ADJUSTED     DW   0
  40. HORZ_REMAINDER    DW   0                       ;Mickey adjustment remainder.
  41. VERT_REMAINDER    DW   0
  42. HORZ_RATIO_REMAIN DW   0                       ;Mickey per pixel remainder.
  43. VERT_RATIO_REMAIN DW   0
  44. HORZ_CURS_REMAIN  DW   0                       ;Text cursor mickey remainder.
  45. VERT_CURS_REMAIN  DW   0
  46. CALL_MASK         DW   0                       ;Subroutine call mask.
  47. INTERRUPT_SUB     DW   0,0                     ;Subroutine address.
  48. VARIABLES_LENGTH  EQU  ($ - MOUSE_VARIABLES) / 2
  49.  
  50. HORZ_RATIO     DW      8                       ;Mickeys / 8 pixel ratio.
  51. VERT_RATIO     DW      16
  52.  
  53. RANGE          DW          3,  5,  7,  9, 12, 23, 32; and above
  54. MULTIPLIER     DW      5,  6, 10, 15, 22, 30, 50, 70
  55. MULTIPLIER_END EQU     $ - 2
  56. MULTIPLIER_LENGTH EQU  ($ - MULTIPLIER) / 2
  57.  
  58. ;                   CODE AREA
  59. ;************* INTERRUPT HANDLERS *************;
  60.  
  61. NEW_INT_33     PROC    FAR
  62.                OR      AX,AX                   ;Is it Reset and Status?
  63.                JNZ     READ_MOUSE
  64.                CALL    MOUSE_DRIVER            ;If yes, call the driver.
  65.                PUSH    AX                      ;Save output.
  66.                PUSH    BX
  67.                PUSH    CX
  68.                PUSH    DX
  69.  
  70.                CALL    RESET                   ;Zero out our variables.
  71.                MOV     CS:HORZ_RATIO,8         ;Restore mickey/pixel ratio.
  72.                MOV     CS:VERT_RATIO,16
  73.                MOV     CX,32767                ;Disable mouse driver cursor
  74.                MOV     DX,CX                   ; control by setting Mickey
  75.                MOV     AX,15                   ; to Pixel ratio very large.
  76.                CALL    MOUSE_DRIVER
  77.                MOV     DX,10000                ;Disable Double-speed by setting
  78.                MOV     AX,19                   ; threshold very large.
  79.                CALL    MOUSE_DRIVER
  80.                MOV     CX,1                    ;Install our interrupt subroutine
  81.                CALL    SET_INTERRUPT
  82.  
  83.                POP     DX                      ;Restore returned values.
  84.                POP     CX
  85.                POP     BX
  86.                POP     AX
  87.                IRET                            ;Return to caller.
  88.  
  89. READ_MOUSE:    CMP     AX,11                   ;Is it Read Mouse
  90.                JNZ     SUBROUTINE              ; Motion Counters?
  91.                CALL    MOUSE_DRIVER            ;If yes, call driver.
  92.                CLI                             ;No interrupts, especially mouse.
  93.                MOV     CX,CS:HORZ_ADJUSTED     ;Return adjusted mickey count.
  94.                MOV     DX,CS:VERT_ADJUSTED
  95.                MOV     CS:HORZ_LAST,0          ;Reset driver mickey count.
  96.                MOV     CS:VERT_LAST,0
  97.                MOV     CS:HORZ_ADJUSTED,0      ;Reset adjusted mickey count.
  98.                MOV     CS:VERT_ADJUSTED,0
  99.                IRET
  100.  
  101. SUBROUTINE:    CMP     AX,12                   ;Is it Set Interrupt Subroutine
  102.                JNZ     SET_RATIO               ; Call Mask and Address?
  103.                MOV     CS:CALL_MASK,CX         ;If yes, store call mask.
  104.                MOV     CS:INTERRUPT_SUB[0],DX  ;Store address.
  105.                MOV     CS:INTERRUPT_SUB[2],ES
  106.                PUSH    CX                      ;Save call mask.
  107.                OR      CX,1                    ;Add Cursor position changes
  108.                CALL    SET_INTERRUPT           ; and install subroutine.
  109.                POP     CX                      ;Restore CX.
  110.                IRET
  111.  
  112. SET_RATIO:     CMP     AX,15                   ;Is it Set Mickey/Pixel Ratio?
  113.                JNZ     SWAP_INT
  114.                MOV     CS:HORZ_RATIO,CX        ;If yes, store requested values.
  115.                MOV     CS:VERT_RATIO,DX
  116.                IRET
  117.  
  118. SWAP_INT:      CMP     AX,20                   ;Is it Swap Interrupt
  119.                JNZ     DOUBLE_SPEED            ; Subroutines?
  120.                PUSH    CS:CALL_MASK            ;If yes, save old call mask
  121.                PUSH    CS:INTERRUPT_SUB[0]     ; and subroutine address.
  122.                PUSH    CS:INTERRUPT_SUB[2]
  123.                MOV     CS:CALL_MASK,CX         ;Store new call mask and
  124.                MOV     CS:INTERRUPT_SUB[0],DX  ; subroutine address.
  125.                MOV     CS:INTERRUPT_SUB[2],BX
  126.                OR      CX,1                    ;Set our subroutine with
  127.                CALL    SET_INTERRUPT           ; new call mask.
  128.                POP     BX                      ;Return old call mask and
  129.                POP     DX                      ; subroutine address.
  130.                POP     CX
  131.                IRET
  132.  
  133. DOUBLE_SPEED:  CMP     AX,19                   ;Skip Double-Speed Threshold.
  134.                JZ      INT_33_END
  135.                CMP     AX,26                   ;Skip Sensitivity.
  136.                JZ      INT_33_END
  137.                JMP     CS:DWORD PTR OLD_INT_33 ;Pass all other calls as is.
  138. INT_33_END:    IRET
  139. NEW_INT_33     ENDP
  140.  
  141. ;----------------------------------------------;
  142. RESET:         PUSH    DI                      ;Preserve registers.
  143.                PUSH    ES
  144.                PUSH    CS
  145.                POP     ES
  146.                XOR     AX,AX                       ;Store zeros in appropriate
  147.                MOV     DI,OFFSET MOUSE_VARIABLES   ; mouse variables.
  148.                MOV     CX,VARIABLES_LENGTH
  149.                CLD                             ;Forward direction.
  150.                CLI                             ;No interrupts.
  151.                REP     STOSW
  152.                POP     ES                      ;Restore registers.
  153.                POP     DI
  154.                RET
  155.  
  156. ;----------------------------------------------;
  157. ; INPUT: CX = Call Mask                        ;
  158. ;----------------------------------------------;
  159. SET_INTERRUPT: PUSH    AX                      ;Preserve registers.
  160.                PUSH    DX
  161.                PUSH    ES
  162.                PUSH    CS
  163.                POP     ES
  164.                MOV     DX,OFFSET MOUSE_CONTROL ;Install our subroutine.
  165.                MOV     AX,12
  166.                CALL    MOUSE_DRIVER
  167.                POP     ES                      ;Restore registers.
  168.                POP     DX
  169.                POP     AX
  170.                RET
  171.  
  172. ;----------------------------------------------;
  173. MOUSE_DRIVER:  PUSHF
  174.                CLI
  175.                CALL    CS:DWORD PTR OLD_INT_33
  176.                RET
  177.  
  178. ;----------------------------------------------;
  179. NEW_INT_10     PROC    FAR
  180.                OR      AH,AH                   ;Video mode change?
  181.                JZ      INT_UPDATE              ;If yes, update variables.
  182.                CMP     AH,11H                  ;Is it User Alpha Load?
  183.                JAE     INT_UPDATE              ;If yes, update variables.
  184.                JMP     CS:DWORD PTR OLD_INT_10 ;Else, no business.
  185. INT_UPDATE:    PUSHF                           ;Update by calling INT 10
  186.                CALL    CS:DWORD PTR OLD_INT_10
  187.                CALL    GET_BIOS_DATA           ;Then retrieve video data.
  188.                IRET
  189. NEW_INT_10     ENDP
  190.  
  191. ;----------------------------------------------;
  192. GET_BIOS_DATA: PUSH    AX                      ;Preserve registers.
  193.                PUSH    DS
  194.                MOV     AX,40H                  ;Point to BIOS data.
  195.                MOV     DS,AX
  196.                MOV     AL,DS:DISPLAY_MODE      ;Retrieve display mode.
  197.                PUSH    CS
  198.                POP     DS                      ;Point to our data.
  199.                MOV     AH,TEXT_MODE            ;Assume text mode.
  200.                MOV     CHAR_WIDTH,16           ;Assume low resolution.
  201.                CMP     AL,1                    ;Is it 40 column?
  202.                JBE     BIOS_END                ;If yes, assumed right.
  203.                MOV     CHAR_WIDTH,8            ;Else, assume high resolution.
  204.                CMP     AL,3                    ;Is it 80 column color or
  205.                JBE     BIOS_END
  206.                CMP     AL,7                    ; MONO?  If yes, assumed right.
  207.                JZ      BIOS_END
  208.  
  209.                MOV     AH,GRAPHICS             ;Else, gotta be graphics mode.
  210.                MOV     GRAPHICS_WIDTH,1        ;Assume low resolution.
  211.                CMP     AL,5                    ;Is it mode 4, 5, D, or 13?
  212.                JBE     BIOS_END                ;If yes, assumed right?
  213.                CMP     AL,0DH
  214.                JZ      BIOS_END
  215.                CMP     AL,13H
  216.                JZ      BIOS_END
  217.                MOV     GRAPHICS_WIDTH,0        ;Else gotta be high resolution.
  218.  
  219. BIOS_END:      MOV     DS:VIDEO_MODE,AH        ;Store video mode.
  220.                POP     DS                      ;Restore registers.
  221.                POP     AX
  222.                RET
  223.  
  224. ;----------------------------------------------;
  225. MOUSE_CONTROL  PROC    FAR
  226.                PUSH    AX                      ;Condition mask.
  227.                PUSH    BX                      ;Button state.
  228.                PUSH    DX                      ;Vertical cursor coordinate.
  229.                PUSH    DI                      ;Vertical Mickeys.
  230.                MOV     BP,CX                   ;Horizontal cursor coordinate.
  231.  
  232.                PUSH    CS                      ;Point to our data
  233.                POP     DS
  234.                PUSH    CS                      ; and extra segment.
  235.                POP     ES
  236.                CLD                             ;All strings forward.
  237.  
  238.                MOV     AX,HORZ_LAST            ;Retrieve last mickey count.
  239.                MOV     HORZ_LAST,SI            ;Last gets new count.
  240.                SUB     SI,AX                   ;SI gets difference since last.
  241.                JZ      VERTICAL                ;If no change, done here.
  242.                MOV     AX,HORZ_REMAINDER       ;Else, retrieve remainder.
  243.                CALL    LOOKUP                  ;Calculate adjusted mickeys.
  244.                ADD     HORZ_ADJUSTED,AX        ;Add to our mickey count.
  245.                MOV     HORZ_REMAINDER,DX       ;Store remainder for next time.
  246.  
  247.                MOV     CX,8                    ;Multiply count by 8.
  248.                IMUL    CX
  249.                MOV     SI,HORZ_RATIO_REMAIN    ;Last ratio remainder.
  250.                MOV     CX,HORZ_RATIO           ;Mickeys per 8 pixels.
  251.                CALL    SIGN_ADD_DIV            ;Calculate Mickey/pixels.
  252.                MOV     HORZ_RATIO_REMAIN,DX    ;Store remainder for next time.
  253.  
  254.                CMP     VIDEO_MODE,GRAPHICS     ;Graphics video mode?
  255.                JNZ     HORZ_TEXT               ;If no, do text cursor.
  256.                CMP     AX,0                    ;Else, are there any mickeys?
  257.                JZ      VERTICAL                ;If no, done here.
  258.                MOV     CX,GRAPHICS_WIDTH       ;Retrieve resolution adjustment.
  259.                JG      ADD_WIDTH               ;Is it positive mickeys?
  260.                NEG     CX                      ;If no, negate adjustment.
  261. ADD_WIDTH:     ADD     AX,CX                   ;Add adjustment value.
  262.                ADD     BP,AX                   ;Add result to cursor position.
  263.                JMP     SHORT VERTICAL          ;Done here.
  264.  
  265. HORZ_TEXT:     ADD     AX,HORZ_CURS_REMAIN     ;Add last remainder.
  266.                CWD                             ;Convert to double word.
  267.                MOV     SI,AX                   ;Store in SI.
  268.                MOV     CX,CHAR_WIDTH           ;Divide by mouse
  269.                IDIV    CX                      ; pixels/character (8 or 16).
  270.                MOV     HORZ_CURS_REMAIN,DX     ;Store remainder for next time.
  271.                SUB     SI,DX                   ;Subtract remainder to get pixels
  272.                ADD     BP,SI                   ;Add result to cursor position.
  273.  
  274. ;----------------------------------------------;
  275. VERTICAL:      POP     SI                      ;Retrieve vertical Mickeys.
  276.                POP     BX                      ;Retrieve vertical coordinate.
  277.                MOV     AX,VERT_LAST
  278.                MOV     VERT_LAST,SI            ;Calculate vertical same as
  279.                SUB     SI,AX                   ; horizontal.
  280.                JZ      MOVE_CURSOR
  281.                MOV     AX,VERT_REMAINDER
  282.                CALL    LOOKUP
  283.                ADD     VERT_ADJUSTED,AX
  284.                MOV     VERT_REMAINDER,DX
  285.  
  286.                MOV     CX,8
  287.                IMUL    CX
  288.                MOV     SI,VERT_RATIO_REMAIN
  289.                MOV     CX,VERT_RATIO
  290.                CALL    SIGN_ADD_DIV
  291.                MOV     VERT_RATIO_REMAIN,DX
  292.  
  293.                CMP     VIDEO_MODE,GRAPHICS
  294.                JNZ     VERT_TEXT
  295.                ADD     BX,AX
  296.                JMP     SHORT MOVE_CURSOR
  297.  
  298. VERT_TEXT:     ADD     AX,VERT_CURS_REMAIN
  299.                CWD
  300.                MOV     SI,AX
  301.                MOV     CX,8
  302.                IDIV    CX
  303.                MOV     VERT_CURS_REMAIN,DX
  304.                SUB     SI,DX
  305.                ADD     BX,SI
  306.  
  307. ;----------------------------------------------;
  308. MOVE_CURSOR:   MOV     CX,BP                   ;New horizontal cursor coordinate
  309.                MOV     DX,BX                   ;New vertical cursor coordinate.
  310.                MOV     AX,4                    ;Set Mouse Cursor.
  311.                CALL    MOUSE_DRIVER
  312.                POP     BX                      ;Retrieve Button state
  313.                POP     AX                      ;Retrieve Condition mask.
  314.                TEST    AX,CALL_MASK            ;Is there a subroutine installed?
  315.                JZ      MOUSE_END               ;If no, done here.
  316.                MOV     SI,HORZ_ADJUSTED        ;Else, pass on vertical mouse
  317.                MOV     DI,VERT_ADJUSTED        ; counts and horizontal mouse
  318.                CALL    DWORD PTR INTERRUPT_SUB ; counts to the subroutine.
  319. MOUSE_END:     RET
  320. MOUSE_CONTROL  ENDP
  321.  
  322. ;--------------------------------------------------------------------;
  323. ;INPUT:  SI = MICKEYS; AX = Last remainder; Flags = sign of MICKEYS. ;
  324. ;OUTPUT: AX = Adjusted MICKEYS, DX = New remainder.                  ;
  325. ;--------------------------------------------------------------------;
  326. LOOKUP:        PUSHF                           ;Save sign.
  327.                JNS     EXCHANGE
  328.                NEG     SI                      ;Absolute value of Mickeys.
  329. EXCHANGE:      XCHG    AX,SI                   ;Store in AX for scan.
  330.                MOV     CX,MULTIPLIER_LENGTH - 1  ;Length of table.
  331.                MOV     DI,OFFSET RANGE         ;Point to table.
  332. NEXT_ACCEL:    SCASW                           ;Scan until Mickeys exceeds
  333.                JB      GOT_ACCEL               ; range.
  334.                LOOP    NEXT_ACCEL
  335. GOT_ACCEL:     POPF                            ;Retrieve sign.
  336.                JNS     MULTIPLY
  337.                NEG     AX                      ;Return sign to Adjusted Mickeys.
  338. MULTIPLY:      MOV     DI,OFFSET MULTIPLIER_END  ;Point to multipliers.
  339.                SHL     CX,1                    ;Retrieve multiplier for
  340.                SUB     DI,CX                   ; appropriate range.
  341.                MOV     CX,[DI]
  342.                IMUL    CX                      ;Multiply.
  343.                MOV     CX,10                   ;Divide to achieve implied
  344.                CALL    SIGN_ADD_DIV            ; decimal point.
  345.                RET
  346.  
  347. ;----------------------------------------------------------------------;
  348. ; Calculates: signed double word DX:AX + SI / CX; OUTPUT: DX:AX=Result ;
  349. ;----------------------------------------------------------------------;
  350. SIGN_ADD_DIV:  XCHG    AX,SI                   ;Place SI in AX to sign extend.
  351.                MOV     DI,DX                   ;DX:AX now in DI:SI.
  352.                CWD                             ;Sign extend AX to DX:AX.
  353.                ADD     AX,SI                   ;Add to DX:DX, DI:SI.
  354.                ADC     DX,DI
  355.                IDIV    CX                      ;Divide DX:AX result by CX.
  356.                RET                             ; and return.
  357.  
  358. ;              DISPOSABLE DATA
  359. ;              ---------------
  360. SYNTAX       LABEL   BYTE
  361.              DB      "Syntax:  MOUSECTL [n ... n | filename | /U]",CR,LF
  362.              DB      "n = up to 8 mouse multipliers with values between 0-32767"
  363.              DB      CR,LF,"defaults = 5,6,10,15,22,30,50,70",CR,LF
  364.              DB      "Implied decimal in values; ie. 5 = 0.5, 18 = 1.8",CR,LF
  365.              DB      "filename = file with multiplier values",CR,LF
  366.              DB      "/U = Uninstall"
  367. CR_LF        DB      CR,LF,LF,"$"
  368.  
  369. NOT_ENOUGH     DB      "Not enough memory",CR,LF,"$"
  370. NOT_FOUND      DB      "File not found",CR,LF,"$"
  371. NO_MOUSE       DB      "Mouse driver not installed so "
  372. NOT_INSTALLED  DB      "MOUSECTL not installed",CR,LF,"$"
  373. UNLOAD_MSG     DB      "MOUSECTL can't be uninstalled",CR,LF
  374.                DB      "Uninstall resident programs in reverse order",CR,LF,"$"
  375. ALLOCATE_MSG   DB      "Memory allocation error",CR,LF,BELL,"$"
  376. INSTALL_MSG    DB      "Installed",CR,LF,"$"
  377. UNINSTALL_MSG  DB      "Uninstalled",CR,LF,"$"
  378.  
  379. ;--------------------------------------------------------------------;
  380. ; Search memory for a copy of our code, to see if already installed. ;
  381. ;--------------------------------------------------------------------;
  382. INITIALIZE     PROC    NEAR
  383.                CLD                             ;All string operations forward.
  384.                MOV     BX,OFFSET START         ;Point to start of code.
  385.                NOT     BYTE PTR [BX]           ;Change a byte so no false match.
  386.                XOR     DX,DX                   ;Start at segment zero.
  387.                MOV     AX,CS                   ;Store our segment in AX.
  388. NEXT_PARAG:    INC     DX                      ;Next paragraph.
  389.                MOV     ES,DX
  390.                CMP     DX,AX                   ;Is it our segment?
  391.                JZ      ANNOUNCE                ;If yes, search is done.
  392.                MOV     SI,BX                   ;Else, point to our signature
  393.                MOV     DI,BX                   ; and offset of possible match.
  394.                MOV     CX,16                   ;Check 16 bytes for match.
  395.                REP     CMPSB
  396.                JNZ     NEXT_PARAG              ;If no match, keep looking.
  397.  
  398. ;----------------------------------------------;
  399. ANNOUNCE:      MOV     DX,OFFSET SIGNATURE     ;Display our signature.
  400.                CALL    PRINT_STRING
  401.                MOV     DX,OFFSET SYNTAX        ;And syntax.
  402.                CALL    PRINT_STRING
  403.  
  404. ;----------------------------------------------;
  405. PARSE:         MOV     SI,81H                  ;Point to command line again.
  406. NEXT_PARSE:    LODSB                           ;Get a byte.
  407.                CMP     AL,CR                   ;Is it carriage return?
  408.                JZ      INSTALL                 ;If yes, done here.
  409.                CMP     AL,"/"                  ;Is it switch character?
  410.                JNZ     CK_NUMBER               ;If no, check if number.
  411.                LODSB                           ;Else, get the switch.
  412.                DEC     SI                      ;Adjust pointer.
  413.                AND     AL,5FH                  ;Capitalize.
  414.                CMP     AL,"U"                  ;Is it "U"?
  415.                JNZ     NEXT_PARSE              ;If no, continue parsing.
  416.                CALL    CK_INSTALLED            ;Else, are we installed?
  417.                MOV     DX,OFFSET NOT_INSTALLED ;If no, exit with error message.
  418.                JZ      MSG_EXIT
  419.                JMP     SHORT UNINSTALL         ;Else, attempt to uninstall.
  420.  
  421. CK_NUMBER:     CMP     AL,"9"                  ;Is it a number?
  422.                JA      CK_FILENAME             ;If no, must be a filename.
  423.                CMP     AL,"0"
  424.                JB      CK_FILENAME
  425.                DEC     SI                      ;Else, adjust pointer.
  426.                JMP     SHORT LOAD_TABLE        ;Load the table with multipliers.
  427.  
  428. CK_FILENAME:   CMP     AL,SPACE                ;Is it a delimiting character?
  429.                JBE     NEXT_PARSE              ;If yes, continue parsing.
  430.                PUSH    SI                      ;Else, save start.
  431. FIND_END:      LODSB                           ;Find the end and convert
  432.                CMP     AL,SPACE                ; to ASCIIZ.
  433.                JA      FIND_END
  434.                MOV     BYTE PTR [SI-1],0
  435.                POP     DX                      ;Retrieve start.
  436.                DEC     DX                      ;Adjust.
  437.                MOV     AX,3D00H                ;Open file for reading.
  438.                INT     21H
  439.                MOV     DX,OFFSET NOT_FOUND     ;Exit with error message if
  440.                JC      MSG_EXIT                ; not found.
  441.                MOV     BX,AX                   ;Else, save handle.
  442.                MOV     DX,OFFSET BUFFER        ;Point to buffer and
  443.                MOV     CX,100                  ; read up to 100 characters.
  444.                MOV     AH,3FH                  
  445.                INT     21H
  446.                MOV     AH,3EH                  ;Close the file.
  447.                INT     21H
  448.                MOV     SI,DX                   ;Point to buffer.
  449.                MOV     BYTE PTR [SI+100],CR    ;Add ending carriage return.
  450.  
  451. LOAD_TABLE:    MOV     DI,OFFSET MULTIPLIER    ;Point to multiplier table.
  452.                MOV     CX,MULTIPLIER_LENGTH    ;Number of entries.
  453. NEXT_MULT:     LODSB                           ;Read a byte.
  454.                CMP     AL,CR                   ;Ending carriage return?
  455.                JZ      INSTALL                 ;If yes, done here.
  456.                CMP     AL,"0"                  ;Is it delimiter?
  457.                JB      NEXT_MULT               ;If yes, next byte.
  458.                DEC     SI                      ;Else, adjust pointer.
  459.                CALL    DECIMAL_HEX             ;Convert decimal to hex.
  460.                STOSW                           ;Store the value.
  461.                LOOP    NEXT_MULT               ;Retrieve all values.
  462.  
  463. ;----------------------------------------------;
  464. INSTALL:       CALL    CK_INSTALLED            ;Check if already installed.
  465.                JZ      CK_MOUSE                ;If no, see if mouse installed.
  466.                OR      AL,AL                   ;Else, done.
  467.                JMP     SHORT EXIT              ;Exit with ERRORLEVEL = 0.
  468.  
  469. ;-------------------------------------------------------------------;
  470. ; Exit.  Return ERRORLEVEL code 0 if successful, 1 if unsuccessful. ;
  471. ;-------------------------------------------------------------------;
  472. MSG_EXIT:      CALL    PRINT_STRING
  473. ERROR_EXIT:    MOV     AL,1                    ;ERRORLEVEL = 1.
  474. EXIT:          MOV     AH,4CH                  ;Terminate.
  475.                INT     21H
  476.  
  477. ;-------------------------------------------------------;
  478. ; This subroutine uninstalls the resident MOUSECTL.COM. ;
  479. ;-------------------------------------------------------;
  480. UNINSTALL:     MOV     CX,ES                   ;Save segment in CX.
  481.                MOV     AX,3533H                ;Get interrupt 33.
  482.                INT     21H
  483.                CMP     BX,OFFSET NEW_INT_33    ;Has it been hooked by another?
  484.                JNZ     UNINSTALL_ERR           ;If yes, exit with error message.
  485.                MOV     BX,ES
  486.                CMP     BX,CX                   ;Is the segment vector same?
  487.                JNZ     UNINSTALL_ERR           ;If no, exit with error message.
  488.  
  489.                MOV     AX,3510H                ;Get interrupt 10.
  490.                INT     21H
  491.                CMP     BX,OFFSET NEW_INT_10    ;Has it been hooked by another?
  492.                JNZ     UNINSTALL_ERR           ;If yes, exit with error message.
  493.                MOV     BX,ES
  494.                CMP     BX,CX                   ;Is the segment vector same?
  495.                JNZ     UNINSTALL_ERR           ;If no, exit with error message.
  496.  
  497.                MOV     AH,49H                  ;Return memory to system pool.
  498.                INT     21H
  499.                MOV     DX,OFFSET ALLOCATE_MSG
  500.                JC      MSG_EXIT                ;Display message if problem.
  501.  
  502.                MOV     DX,ES:OLD_INT_33[0]     ;Restore old INT 33.
  503.                MOV     DS,ES:OLD_INT_33[2]
  504.                MOV     AX,2533H
  505.                INT     21H
  506.                MOV     DX,ES:OLD_INT_10[0]     ;Restore old INT 10.
  507.                MOV     DS,ES:OLD_INT_10[2]
  508.                MOV     AX,2510H
  509.                INT     21H
  510.  
  511.                XOR     AX,AX                   ;Mouse Reset.
  512.                INT     33H
  513.  
  514.                PUSH    CS
  515.                POP     DS                      ;Point to our data.
  516.                MOV     DX,OFFSET UNINSTALL_MSG ;Display uninstall message.
  517.                CALL    PRINT_STRING
  518.                XOR     AL,AL                   ;Exit with ERRORLEVEL = 0.
  519.                JMP     EXIT
  520.  
  521. UNINSTALL_ERR: MOV     ES,CX                   ;If error, exit
  522.                MOV     DX,OFFSET UNLOAD_MSG    ; with error message.
  523.                JMP     MSG_EXIT
  524.  
  525. ;--------------------------------;
  526. ; This is the install procedure. ;
  527. ;--------------------------------;
  528. CK_MOUSE:      MOV     AX,3533H                ;Else, get INT 33 vector.
  529.                INT     21H
  530.                MOV     AX,ES
  531.                OR      AX,AX                   ;If vector zero, no mouse driver.
  532.                MOV     DX,OFFSET NO_MOUSE
  533.                JZ      MSG_EXIT
  534.                MOV     AL,ES:[BX]
  535.                CMP     AL,IRET_CODE
  536.                JZ      MSG_EXIT
  537.                MOV     OLD_INT_33[0],BX        ;Save old interrupt.
  538.                MOV     OLD_INT_33[2],ES
  539.                MOV     DX,OFFSET NEW_INT_33    ;Install new interrupt.
  540.                MOV     AX,2533H
  541.                INT     21H
  542.  
  543.                XOR     AX,AX
  544.                INT     33H                     ;Initialize driver.
  545.                CALL    GET_BIOS_DATA           ;Get video mode.
  546.  
  547.                MOV     AX,3510H                ;Get INT 10 vector.
  548.                INT     21H
  549.                MOV     OLD_INT_10[0],BX        ;Save old interrupt.
  550.                MOV     OLD_INT_10[2],ES
  551.                MOV     DX,OFFSET NEW_INT_10    ;Install new interrupt.
  552.                MOV     AX,2510H
  553.                INT     21H
  554.  
  555.                MOV     AX,DS:[2CH]             ;Get environment segment.
  556.                MOV     ES,AX
  557.                MOV     AH,49H                  ;Free up environment.
  558.                INT     21H
  559.  
  560.                MOV     DX,OFFSET INSTALL_MSG   ;Display install message.
  561.                CALL    PRINT_STRING
  562.                MOV     DX,OFFSET SYNTAX        ;End of resident portion.
  563.                ADD     DX,15                   ;Round up.
  564.                MOV     CL,4
  565.                SHR     DX,CL                   ;Convert to paragraphs.
  566.                MOV     AX,3100H                ;Return error code of zero.
  567.                INT     21H                     ;Terminate but stay resident.
  568. INITIALIZE     ENDP
  569.  
  570. ;-------------------------------------------------------;
  571. ; OUTPUT: ZR = 1 if not installed; ZR = 0 if installed. ;
  572. ;-------------------------------------------------------;
  573. CK_INSTALLED:  MOV     AX,ES
  574.                MOV     BX,CS
  575.                CMP     AX,BX                   ;Compare segments.
  576.                RET
  577.  
  578. ;-------------------------------------------------------------; 
  579. ; INPUT: SI points to decimal number; OUTPUT: AX = hex number ;
  580. ;-------------------------------------------------------------;
  581. DECIMAL_HEX:   XOR     BX,BX
  582. NEXT_DECIMAL:  LODSB                           ;Get a character.
  583.                SUB     AL,"0"                  ;ASCII to binary.
  584.                JC      DECIMAL_END             ;If not between 0 and 9, skip.
  585.                CMP     AL,9
  586.                JA      DECIMAL_END
  587.                CBW                             ;Convert to word.
  588.                XCHG    AX,BX                   ;Swap old and new number.
  589.                MOV     DX,10                   ;Shift to left by multiplying
  590.                MUL     DX                      ; last entry by ten.
  591.                ADD     BX,AX                   ;Add new number and store in BX.
  592.                JMP     NEXT_DECIMAL
  593. DECIMAL_END:   MOV     AX,BX                   ;Return in AX.
  594.                DEC     SI                      ;Adjust pointer.
  595.                RET
  596.  
  597. ;----------------------------------------------;
  598. PRINT_STRING:  MOV     AH,9
  599. DOS_INT:       INT     21H                     ;Print string via DOS.
  600.                RET
  601.  
  602. BUFFER         EQU     $
  603.  
  604. _TEXT          ENDS
  605.                END     START
  606.